package com.autumn.sms;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.autumn.util.ExceptionUtils;
import com.autumn.util.StringUtils;
import com.autumn.validation.MatchesUtils;

/**
 * 短信发送抽象
 * 
 * @author 杨昌国 2018-12-07 10:37:51
 */
public abstract class AbstractSmsChannel implements SmsChannel {

	/**
	 * 日志
	 */
	private final Log logger = LogFactory.getLog(this.getClass());

	private SmsChannelListen channelListen;

	/**
	 * 获取日志
	 * 
	 * @return
	 */
	public final Log getLogger() {
		return this.logger;
	}

	/**
	 * 获取通道监听
	 * 
	 * @return
	 */
	public SmsChannelListen getChannelListen() {
		return this.channelListen;
	}

	/**
	 * 设置通道监听
	 * 
	 * @param channelListen
	 *            通道监听
	 */
	public void setChannelListen(SmsChannelListen channelListen) {
		this.channelListen = channelListen;
	}

	/**
	 * 手机号分隔
	 * 
	 * @param phoneNumbers
	 *            手机号列表
	 * @return
	 */
	protected final String[] toPhoneNumberArray(String phoneNumbers) {
		String[] phones = phoneNumbers.split("\\,");
		return phones;
	}

	/**
	 * 转换为电话号码列表
	 * 
	 * @param phoneNumbers
	 *            手机号列表
	 * @return
	 */
	protected final ArrayList<String> toPhoneNumberList(String phoneNumbers) {
		String[] phones = toPhoneNumberArray(phoneNumbers);
		ArrayList<String> numbers = new ArrayList<>();
		for (String phone : phones) {
			numbers.add(phone);
		}
		return numbers;
	}

	/**
	 * 手机号分页
	 * 
	 * @param phoneNumbers
	 *            手机号码集合
	 * @param nationCode
	 *            国家代码
	 * @param pageSize
	 *            页大小
	 * @return
	 */
	protected final List<String> phoneNumberPages(String phoneNumbers, String nationCode, int pageSize) {
		if (nationCode == null) {
			nationCode = "";
		} else {
			nationCode = nationCode.trim();
		}
		List<String> phonePages = new ArrayList<>();
		String[] phones = this.toPhoneNumberArray(phoneNumbers);
		int index = 0;
		StringBuilder sb = new StringBuilder();
		for (String phone : phones) {
			if (sb.length() > 0) {
				sb.append(",");
			}
			sb.append(nationCode + phone);
			index++;
			if (index >= pageSize) {
				phonePages.add(sb.toString());
				index = 0;
				sb = new StringBuilder();
			}
		}
		if (sb.length() > 0) {
			phonePages.add(sb.toString());
		}
		return phonePages;
	}

	/**
	 * 
	 * @param phoneNumbers
	 */
	private String checkPhoneNumbers(String phoneNumbers) {
		StringBuilder sb = new StringBuilder();
		String[] phones = this.toPhoneNumberArray(phoneNumbers);
		for (String phone : phones) {
			if (!StringUtils.isNullOrBlank(phone)) {
				if (!MatchesUtils.isMobilePhone(phone)) {
					ExceptionUtils.throwValidationException("手机号码[" + phone + "]无效。");
				}
				if (sb.length() > 0) {
					sb.append(",");
				}
				sb.append(phone);
			}
		}
		return sb.toString();
	}

	/**
	 * 
	 * @param message
	 */
	private void initMessage(SmsMessage message) {
		message.setPhoneNumbers(checkPhoneNumbers(message.getPhoneNumbers()));
		if (message.getCreate() == null) {
			message.setCreate(new Date());
		}
		if (message.getParams() == null) {
			message.setParams(new LinkedHashMap<>());
		}
	}

	/**
	 * 
	 */
	@Override
	public final void send(SmsMessage message) throws Exception {
		this.send(message, new MapSmsChannelConfigure());
	}

	/**
	 * 
	 */
	@Override
	public final void send(SmsMessage message, SmsChannelConfigure channelConfigure) throws Exception {
		ExceptionUtils.checkNotNull(message, "message");
		if (StringUtils.isNullOrBlank(message.getTemplateCode())) {
			ExceptionUtils.throwValidationException("模板代码不能为空。");
		}
		if (StringUtils.isNullOrBlank(message.getPhoneNumbers())) {
			ExceptionUtils.throwValidationException("至少需要一个以上手机号码。");
		}
		this.initMessage(message);
		if (channelConfigure == null) {
			channelConfigure = new MapSmsChannelConfigure();
		}
		String platform = String.format("[%s %s]", this.getChannelCode(), this.getChannelName());
		SmsChannelListen listen = this.getChannelListen();
		Date start = new Date();
		Date end;
		try {
			this.InternalSend(message, channelConfigure);
			end = new Date();
			if (this.getLogger().isDebugEnabled()) {
				this.getLogger().debug(platform + "发送短信成功:" + message.toString());
			}
			if (listen != null) {
				listen.sendSuccess(this, new ChannelListenMessage(start, end, message, channelConfigure));
			}
		} catch (Exception e) {
			end = new Date();
			this.getLogger().error(platform + "发送短信出错:" + e.getMessage() + " " + message.toString(), e);
			if (listen != null) {
				listen.sendError(this, new ChannelListenMessage(start, end, message, channelConfigure), e);
			}
			throw e;
		}
	}

	/**
	 * 内部发送短信
	 * 
	 * @param message
	 *            短信消息
	 * @param channelConfigure
	 *            通道配置
	 */
	protected abstract void InternalSend(SmsMessage message, SmsChannelConfigure channelConfigure) throws Exception;
}
